package com.seckill.controller;

import com.seckill.entity.Result;
import com.seckill.model.SuccessKilled;
import com.seckill.service.SeckillService;
import com.seckill.service.SuccessKilledService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.sql.Timestamp;
import java.util.Iterator;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: hualao
 * @Version: 0.0.1V
 * @Date: 2019/1/24
 * @Description: 秒杀
 **/
@Slf4j
@RequestMapping("seckill")
@RestController
public class SeckillController {

    @Autowired
    private SuccessKilledService successKilledService;

    @Autowired
    private SeckillService seckillService;

    private static int corePoolSize = Runtime.getRuntime().availableProcessors();
    /**
     * @Author: hualao
     * @Date: 2019/1/24 14:00
     * @Description: 使用线程池创建线程
     **/
    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, corePoolSize + 1, 10l, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(1000));

    private static Queue queue = new LinkedBlockingQueue(10);

    /**
     * @Author: hualao
     * @Date: 2019/1/24 13:05
     * @Description: 秒杀最low的实现方式
     **/
    @PostMapping("start")
    public Result start(long seckillId) {
        //初始化库存
        seckillService.initNumberBySeckillId(seckillId);
        //假设初始化N个购买者
        int seckillNum = 100;
        final CountDownLatch latch = new CountDownLatch(seckillNum);
        //清空该秒杀商品的成功信息
        successKilledService.deleteBySeckillId(seckillId);
        log.info("开始秒杀 ---> {}", "");
        for (int i = 0; i < seckillNum; i++) {
            final long userId = i;
            executor.execute(() -> {
                //开始秒杀
                Result result = seckillService.startSeckil(seckillId, userId);
                if (result != null) {
                    log.info("用户:{}{}", userId, result.get("msg"));
                } else {
                    log.info("用户:{}{}", userId, "哎呦喂，人也太多了，请稍后！");
                }
                latch.countDown();
            });
        }
        //等待所有人执行任务结束
        try {
            latch.await();
            int count = successKilledService.successCount(seckillId);
            log.info("一共秒杀出{}件商品", count);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return Result.ok();
    }

    /**
     * @Author: hualao
     * @Date: 2019/1/24 13:05
     * @Description: 秒杀使用队列方式
     **/
    @PostMapping("startQueue")
    public Result startQueue(long seckillId) {

        if (queue.size() == 10) {
            //触发发送奖励
            createOrder();
            return Result.error("秒杀结束商品已售完");
        }

        //初始化库存
        seckillService.initNumberBySeckillId(seckillId);
        //假设初始化N个购买者
        SuccessKilled successKilled = new SuccessKilled();
        successKilled.setUserId((long) new Random().nextInt(999999));
        successKilled.setSeckillId(seckillId);
        successKilled.setCreateTime(new Timestamp(System.currentTimeMillis()));
        successKilled.setState((short) 0);
        try {
            queue.add(successKilled);
        } catch (IllegalStateException e) {
            e.printStackTrace();
            return Result.error("秒杀结束商品已售完");
        }
        return Result.ok();
    }

    private void createOrder() {
        Iterator iterator = queue.iterator();
        while (iterator.hasNext()) {
            SuccessKilled successKilled = (SuccessKilled) iterator.next();
            log.info("创建订单 --> {}", successKilled.getUserId());
        }
    }


    public static void main(String[] args) {
        System.out.println(new Random().nextLong());
    }

}
